Energy Engineer (UnB) │ Data Scientist and Analytics (USP)
🇬🇧 - English
This Jupyter Notebook is a Data Exploration for the purpose of providing the Dashboard Report with the most pertinent information. It first uploads previously treated data and then analyzes it in statistical and visual ways.
This Data Exploration process composes the flow of a data engineering solution developed to provide Brazilian electric generation data in a dashboard type report, prioritizing to be iterative, dynamic and autonomous. Accessible by specialists in a timely manner.
For better understanding, the code has been divided into five parts:
load_data() function is created to load the
data and present its first information, referring to the DataFrame
generation date and updates from the Brazilian Electric Energy Agency
server.Categorical Variables Analyses:
These analyses were critical, since the vast majority of the variables in this DataFrame are categorical.
First the unique values of each categorical variable are checked.
These values are then analyzed via an alluvial diagram, enabling a hierarchization of the variables.
DateTime Analyses:
It is known that outliers exist in this data, since in the ETL process null values were replaced by the year "1900".
Because of this, the data that does not contain outliers of this type is filtered.
Finally, temporal analyses are performed:
Categorical & Numerical Variables Analyses:
Hierarchical Analyses:
Analysis between variables:
Geographical Variables Analyses*:
The detailed step-by-step is presented below.
🇧🇷 - Portuguese
Este Jupyter Notebook é uma Exploração de Dados com o foco em subsidiar o *Relatório em Dashboard com as informações mais pertinentes. Primeiro são carregados dados previamente tratados e para depois os analisar de formas estatísticas e visuais.
Esta Exploração de Dados compõe o fluxo da solução em engenharia de dados desenvolvida para apresentar dados de geração do setor elétrico brasileiro em um relatório do tipo dashboard, priorizando ser iterativo, dinâmico e autônomo. Acessível por especialistas de forma tempestiva.
Para melhor compreensão, o código foi dividido em cinco partes:
load_data() para carregar os
dados e apresentar suas primeiras informações, referentes à data de
geração do DataFrame e atualizações do servidor da Agência Nacional de
Energia Elétrica.Categorical Variables Analyses:
Estas análises foram fundamentais, uma vez que a grande maioria das variáveis deste DataFrame são categóricas.
Primeiro são verificados os valores únicos de cada variável categórica.
Estes valores são então analizados via diagrama aluvial, possibilitando uma hierarquização das variáveis.
DateTime Analyses:
Sabe-se que existem outliers nestes dados, uma vez que no processo de ETL valores nulos foram substituídos pelo ano "1900".
Por conta disso, filtram-se os dados que não contém outliers deste tipo.
Por fim, são realizadas análises temporais:
Categorical & Numerical Variables Analyses:
Análises Hierarquicas:
Análises entre variáveis:
Geographical Variables Analyses:
O passo a passo detalhado é apresentado abaixo, em inglês.
# Library imports
## Data Exploration & Vizualization libraries
import pandas as pd
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import plotly.express as px
import plotly as plt
import plotly.figure_factory as ff
import plotly.graph_objects as go
## Web Scrapping library
import requests
# Functions
def linha(x):
# Generates a Line with the input simbol
print(x*50)
def load_data():
# Function for loading data
# Server request, dataframe generation and consolidation of DateTime variables
patch = r"https://raw.githubusercontent.com/viniciusgribas/Analise_dados_geracao_BR/main/Analise_Geracao_II/Notebooks/output/CSV/Generation_Data.csv"
response_API = requests.get(patch)
df = pd.read_csv(patch ,encoding='utf-8')
df.DatEntradaOperacao = pd.to_datetime(df.DatEntradaOperacao)
df.DatInicioVigencia = pd.to_datetime(df.DatInicioVigencia)
df.DatFimVigencia = pd.to_datetime(df.DatFimVigencia)
df.ETL_CreatedDataLoad_At = pd.to_datetime(df.ETL_CreatedDataLoad_At)
df.ETL_DataBase_LastModified = pd.to_datetime(df.ETL_DataBase_LastModified)
# Additional informations
print('CREATION DATE [',df.ETL_CreatedDataLoad_At[1], ']') # Time this file was generated by the ETL
print('LAST SERVER UPDATE ON DATA [',df.ETL_DataBase_LastModified[1],']') # Time the host last updated the file
return (df)
# Personal Label
github = "_GitHub_@viniciusgribas"
# Data Load
df = load_data()
# VARIABLE CLASSIFICATION
#### Column Dtype Variable Type
## --- ------ ----- ---------- │
## Empreendimento │ object │ CATEGORICAL-NOMINAL │
## UF │ object │ CATEGORICAL-NOMINAL │
## TipoGeracao │ object │ CATEGORICAL-NOMINAL │
## Fase │ object │ CATEGORICAL-ORDINAL │
## OrigemCombustivel │ object │ CATEGORICAL-NOMINAL │
## FonteCombustivel │ object │ CATEGORICAL-NOMINAL │
## Outorga │ object │ CATEGORICAL-ORDINAL │
## NomeCombustivel │ object │ CATEGORICAL-ORDINAL │
## DatEntradaOperacao │ datetime64 │ CATEGORICAL-DATETIME │
## MdaPotenciaOutorgadaKW │ float64 │ NUMERICAL-CONTINOUS-RATIO │
## MdaPotenciaFiscalizadaKW │ int64 │ NUMERICAL-DISCRETE │
## MdaGarantiaFisicaKW │ float64 │ NUMERICAL-CONTINOUS-RATIO │
## GeracaoQualificada │ object │ CATEGORICAL-BINARY │
## Y │ float64 │ NUMERICAL-CONTINOUS-INTERVAL*│
## X │ float64 │ NUMERICAL-CONTINOUS-INTERVAL*│
## DatInicioVigencia │ datetime64 │ CATEGORICAL-DATETIME │
## DatFimVigencia │ datetime64 │ CATEGORICAL-DATETIME │
## ETL_CreatedDataLoad_At │ datetime64 │ CATEGORICAL-DATETIME │
## ETL_DataBase_LastModified │ datetime64 │ CATEGORICAL-DATETIME │
### *Geographical Variables
# ----------------------------------------------------------------------------------------------
# VARIABLE METADATA
# | Variable | Type | Meaning |
# |--------------------------|-------------|------------------------------|
# | MdaGarantiaFisicaKW | Numerical | Physical Guarantee of Energy |
# | MdaPotenciaFiscalizadaKW | Numerical | Supervised Electric Power |
# | MdaPotenciaOutorgadaKW | Numerical | Granted Electric Power |
# | Empreendimento | Categorical | Business Name |
# | UF | Categorical | Brasil States |
# | TipoGeracao | Categorical | Generation Type |
# | Fase | Categorical | Operational Phase |
# | OrigemCombustivel | Categorical | Fuel Origin |
# | FonteCombustivel | Categorical | Fuel Source |
# | NomeCombustivel | Categorical | Fuel Name |
# | Outorga | Categorical | Grant |
# | GeracaoQualificada | Categorical | Qualified Generation Mode |
# | DatEntradaOperacao | Date-Time | Operation Start Date |
# | DatInicioVigencia | Date-Time | Start Date of Contract |
# | DatFimVigencia | Date-Time | End Date of Contract |
# | X | Geographic | Longitude Values |
# | Y | Geographic | Latitude Values |
# │ ETL_CreatedDataLoad_At │ Date-Time | DataFrame creation date |
# │ ETL_DataBase_LastModified│ Date-Time | DataFrame Last Updated |
# Analyze the columns names
df.info()
CREATION DATE [ 2022-04-24 03:03:46 ] LAST SERVER UPDATE ON DATA [ 2022-04-19 20:13:45 ] <class 'pandas.core.frame.DataFrame'> RangeIndex: 15469 entries, 0 to 15468 Data columns (total 19 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Empreendimento 15469 non-null object 1 UF 15469 non-null object 2 TipoGeracao 15469 non-null object 3 Fase 15469 non-null object 4 OrigemCombustivel 15469 non-null object 5 FonteCombustivel 15469 non-null object 6 Outorga 15469 non-null object 7 NomeCombustivel 15469 non-null object 8 DatEntradaOperacao 15469 non-null datetime64[ns] 9 MdaPotenciaOutorgadaKW 15469 non-null float64 10 MdaPotenciaFiscalizadaKW 15469 non-null int64 11 MdaGarantiaFisicaKW 15469 non-null float64 12 GeracaoQualificada 15469 non-null object 13 Y 15469 non-null float64 14 X 15469 non-null float64 15 DatInicioVigencia 15469 non-null datetime64[ns] 16 DatFimVigencia 15469 non-null datetime64[ns] 17 ETL_CreatedDataLoad_At 15469 non-null datetime64[ns] 18 ETL_DataBase_LastModified 15469 non-null datetime64[ns] dtypes: datetime64[ns](5), float64(4), int64(1), object(9) memory usage: 2.2+ MB
# Considering that most variables in this DataFrame are categorical, it is important to hierarchize them, making it more intuitive.
# Unique Values Analyses.
print(df.select_dtypes(['object']).nunique().sort_values())
linha('*')
print('GeracaoQualificada - Unique',df.GeracaoQualificada.unique())
linha('-')
print('Fase - Unique',df.Fase.unique())
linha('-')
print('Outorga - Unique',df.Outorga.unique())
linha('-')
print('OrigemCombustivel - Unique',df.OrigemCombustivel.unique())
linha('-')
print('TipoGeracao - Unique',df.TipoGeracao.unique())
linha('-')
print('FonteCombustivel - Unique',df.FonteCombustivel.unique())
linha('-')
print('UF - Unique',df.UF.unique())
linha('-')
print('NomeCombustivel - Unique',df.NomeCombustivel.unique())
# By the number of unique values, a possible hierarchical order is:
# 'GeracaoQualificada' > 'Fase' > 'Outorga' > OrigemCombustivel > TipoGeracao > FonteCombustivel > UF
GeracaoQualificada 2 Fase 3 Outorga 3 OrigemCombustivel 7 TipoGeracao 8 FonteCombustivel 14 UF 27 NomeCombustivel 32 Empreendimento 15207 dtype: int64 ************************************************** GeracaoQualificada - Unique ['Não' 'Sim'] -------------------------------------------------- Fase - Unique ['Operação' 'Construção não iniciada' 'Construção'] -------------------------------------------------- Outorga - Unique ['Autorização' 'Concessão' 'Registro'] -------------------------------------------------- OrigemCombustivel - Unique ['Hídrica' 'Fóssil' 'Biomassa' 'Nuclear' 'Eólica' 'Solar' 'Undi-Elétrica'] -------------------------------------------------- TipoGeracao - Unique ['PCH' 'UHE' 'CGH' 'UTE' 'UTN' 'EOL' 'UFV' 'CGU'] -------------------------------------------------- FonteCombustivel - Unique ['Potencial hidráulico' 'Carvão mineral' 'Petróleo' 'Agroindustriais' 'Gás natural' 'Urânio' 'Floresta' 'Resíduos sólidos urbanos' 'Cinética do vento' 'Radiação solar' 'Outros Fósseis' 'Cinética da água' 'Resíduos animais' 'Biocombustíveis líquidos'] -------------------------------------------------- UF - Unique ['MG' 'RS' 'SC' 'TO' 'RR' 'MT' 'SP' 'ES' 'RO' 'AM' 'AP' 'RJ' 'PR' 'CE' 'BA' 'PA' 'MA' 'PI' 'AL' 'GO' 'PB' 'MS' 'PE' 'DF' 'SE' 'RN' 'AC'] -------------------------------------------------- NomeCombustivel - Unique ['Potencial hidráulico' 'Gás de Alto Forno - CM' 'Óleo Diesel' 'Bagaço de Cana de Açúcar' 'Gás Natural' 'Urânio' 'Licor Negro' 'Óleo Combustível' 'Calor de Processo - CM' 'Outros Energéticos de Petróleo' 'Carvão Mineral' 'Resíduos Florestais' 'Calor de Processo - GN' 'Gás de Refinaria' 'Biogás - RU' 'Cinética do vento' 'Lenha' 'Casca de Arroz' 'Radiação solar' 'Carvão Vegetal' 'Gás de Alto Forno - PE' 'Gás de Alto Forno - Biomassa' 'Calor de Processo - OF' 'Cinética da água' 'Biogás - RA' 'Capim Elefante' 'Óleos vegetais' 'Biogás-AGR' 'Resíduos Sólidos Urbanos - RU' 'Biogás - Floresta' 'Etanol' 'Carvão - RU']
# Visualizing the relationship and variables hierarchy.
fig = px.parallel_categories(df,
dimensions = ['GeracaoQualificada','Fase','Outorga','OrigemCombustivel','TipoGeracao','FonteCombustivel','NomeCombustivel'],
labels ={'GeracaoQualificada','Fase','Outorga','OrigemCombustivel','TipoGeracao','FonteCombustivel','NomeCombustivel'}
)
# UF - [Not used in this view]
# GeracaoQualificada
# Fase
# Outorga
# OrigemCombustivel
# TipoGeracao
# FonteCombustivel
# NomeCombustivel
fig.show()
# There are outliers in the year 1900
# To analyze variables with dates, two new variables are created:
## 'df_data' and 'df_data_op' without outliers.
df_data = df.get(df['DatInicioVigencia']>'1901')
df_data = df.get(df['DatFimVigencia']>'1901')
df_data_op = df.get(df['DatEntradaOperacao']>'1901')
fig = px.box(df_data,
title='DatInicioVigencia',
x='TipoGeracao',
y="DatInicioVigencia",
hover_name='Empreendimento',
color='TipoGeracao',
points="all")
fig.show()
fig = px.box(df_data,
title='DatFimVigencia',
x='TipoGeracao',
color='TipoGeracao',
y="DatFimVigencia",
hover_name='Empreendimento',
points="all")
fig.show()
fig = px.box(df_data_op,
title='DatEntradaOperacao',
x='TipoGeracao',
color='TipoGeracao',
y="DatEntradaOperacao",
hover_name='Empreendimento',
points="all")
fig.show()
fig = px.histogram(df_data,
title='DatInicioVigencia',
x="DatInicioVigencia",
marginal='violin',
color = 'Fase',
barmode='group',
animation_frame='TipoGeracao',
labels='TipoGeracao',
range_y = (0,300),
)
fig.show()
fig = px.histogram(df_data,
title='DatFimVigencia',
x="DatFimVigencia",
marginal='violin',
color = 'Fase',
barmode='group',
animation_frame='TipoGeracao',
labels='TipoGeracao',
range_y = (0,300),
)
fig.show()
fig = px.histogram(df_data_op,
title='DatEntradaOperacao',
x="DatEntradaOperacao",
marginal='violin',
color = 'Fase',
barmode='group',
animation_frame='TipoGeracao',
labels='TipoGeracao',
range_y = (0,300),
)
fig.show()
fig_dens = px.density_heatmap(df_data,
title='Timeline - GrantedPower - DatInicioVigencia',
x="DatInicioVigencia",
y="TipoGeracao",
z= "MdaPotenciaOutorgadaKW" ,
marginal_x="histogram",
marginal_y="histogram",
text_auto=True
)
fig_dens.show()
fig_dens = px.density_heatmap(df_data,
title='Timeline - GrantedPower - DatFimVigencia',
x="DatFimVigencia",
y="TipoGeracao",
z= "MdaPotenciaOutorgadaKW" ,
marginal_x="histogram",
marginal_y="histogram",
text_auto=True
)
fig_dens.show()
fig_dens = px.density_heatmap(df_data_op,
title='Timeline - GrantedPower - DatEntradaOperacao',
x="DatEntradaOperacao",
y="TipoGeracao",
z= "MdaPotenciaOutorgadaKW" ,
marginal_x="histogram",
marginal_y="histogram",
text_auto=True
)
fig_dens.show()
round(df.describe(),2)
| MdaPotenciaOutorgadaKW | MdaPotenciaFiscalizadaKW | MdaGarantiaFisicaKW | Y | X | |
|---|---|---|---|---|---|
| count | 15469.00 | 15469.00 | 15469.00 | 15469.00 | 15469.00 |
| mean | 15986.58 | 11826.26 | 5979.22 | -8.16 | -38.24 |
| std | 156839.41 | 155249.73 | 96488.49 | 9.25 | 20.72 |
| min | 0.16 | 0.00 | 0.00 | -33.72 | -72.81 |
| 25% | 1.00 | 1.00 | 0.00 | -15.82 | -52.26 |
| 50% | 1.38 | 1.00 | 0.00 | -3.78 | -48.15 |
| 75% | 4000.00 | 720.00 | 0.00 | -1.74 | -36.75 |
| max | 11233100.00 | 11233100.00 | 7772900.00 | 4.89 | 0.00 |
size = 750
fig_IcicleChart = px.icicle(df,
path=[px.Constant('BRASIL'),
'Fase',
"UF",
'TipoGeracao'],
values='MdaPotenciaOutorgadaKW',
title= 'Granted Power by Phase, Type of Generation and States in Brazil',
width=size,
height=size*2,
maxdepth = -1 )
fig_IcicleChart.update_traces(root_color="lightgrey")
fig_IcicleChart.update_layout(margin = dict(t=50, l=50, r=50, b=50))
fig_IcicleChart.show()
# plt.offline.plot(fig_IcicleChart, filename = title_IcicleChart_export)
size = 750
fig_SunBurstChart = px.sunburst(df,
path=[px.Constant('BRASIL'),
'Fase',
"UF",
'TipoGeracao'],
values='MdaPotenciaOutorgadaKW',
title= 'Granted Power by Phase, Type of Generation and States in Brazil',
width=size,
height=size*2,
maxdepth = -1 )
fig_SunBurstChart.update_traces(root_color="lightgrey")
fig_SunBurstChart.update_layout(margin = dict(t=50, l=50, r=50, b=50))
fig_SunBurstChart.show()
size = 750
fig_treemapChart = px.treemap(df,
path=[px.Constant('BRASIL'),
"Fase",
'OrigemCombustivel',
'FonteCombustivel',
'UF'
],
values='MdaPotenciaOutorgadaKW',
title= 'Granted Power by Phase, Type of Generation and States in Brazil',
width=size*2,
height=size,
maxdepth = -1 )
fig_treemapChart.update_traces(root_color="lightgrey")
fig_treemapChart.update_layout(margin = dict(t=50, l=50, r=50, b=50))
fig_treemapChart.show()
fig_BarChart = px.bar(df,
x="UF",
y="MdaPotenciaOutorgadaKW",
color="TipoGeracao",
hover_name='Fase',
title='Bar Chart - Power Granted by State, Generation Type and Phase',
width=800,
height=1000,
animation_frame='Fase'
)
fig_BarChart.show()
fig_Strip = px.strip(df,
x="MdaPotenciaOutorgadaKW",
y="UF",
orientation="h",
hover_name="Empreendimento",
title = 'Strip Chart - Power Granted by States, Generation Type, Phase and Business',
color="TipoGeracao",
animation_frame='Fase'
)
fig_Strip.show()
# Filtering only the enterprises with physical guarantees of generation
dfGuarantee=df.get(df.MdaGarantiaFisicaKW > 0)
fig = px.scatter_3d(dfGuarantee,
x='MdaPotenciaOutorgadaKW',
y='MdaGarantiaFisicaKW',
z='UF',
color='TipoGeracao',
title= '3D Chart - Granted Power and Physical Guarantee by States and Generation Type',
hover_name='Empreendimento',
symbol='TipoGeracao',
animation_frame='Fase')
fig.show()
# There are outliers in the latitude/longitute 0
# To analyze variables with geographical values, a new variable are created:
## 'df_map' without outliers.
df_map = df.get(df['X']!=0.0)
fig_pointsMap = px.scatter_mapbox(df_map,
lat="Y",
lon="X",
color="TipoGeracao",
size="MdaPotenciaOutorgadaKW",
color_continuous_scale=px.colors.sequential.matter,
hover_name = "Empreendimento",
hover_data = ["MdaPotenciaOutorgadaKW"],
title= 'Iterative Cartesian Coordinate Map',
size_max=80,
zoom=3,
mapbox_style='open-street-map',
animation_frame='Fase'
)
fig_pointsMap.show()